package com.derbysoft.lowcostadapter.schedule.sync.impl;

import com.derbysoft.lowcostadapter.commons.redis.service.JedisClusterService;
import com.derbysoft.lowcostadapter.commons.repository.SystemVariableRepository;
import com.derbysoft.lowcostadapter.commons.utils.DateTimeUtils;
import com.derbysoft.lowcostadapter.dswitch2.service.helper.Constant;
import com.derbysoft.lowcostadapter.schedule.net.FTPUtils;
import com.derbysoft.lowcostadapter.schedule.sync.SyncFtpFilesService;
import com.derbysoft.lowcostadapter.schedule.sync.SyncService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * User: jason
 * Date: 2012-11-01
 */
public class SyncFileServiceImpl implements SyncFtpFilesService {

    private static Logger logger = LoggerFactory.getLogger(SyncFileServiceImpl.class);

    protected AtomicBoolean running = new AtomicBoolean(false);

    private SystemVariableRepository systemVariableRepository;

    private List<SyncService> syncServices;

    private JedisClusterService jedisClusterService;

    @Override
    public void syncEnforce() {
        running.set(true);

        syncAll();

        running.set(false);
    }

    @Override
    public synchronized void sync() {
        running.set(true);
        try {
            if (FTPUtils.checkSyncFiles(getSyncFiles())) {
                syncAll();
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        running.set(false);
    }

    @Override
    public List<String> getLocalFiles() {
        List<String> fileNames = new ArrayList<String>();
        List<SyncFile> syncFiles = getSyncFiles();
        for (SyncFile syncFile : syncFiles) {
            File file = new File(FTPUtils.getLocalFilePathName(syncFile.getName()));
            if (file.exists()) {
                String lastUpdateTime = DateTimeUtils.formatDateTime(new Date(file.lastModified()));
                fileNames.add(String.format("%s, %s, %d", file.getName(), lastUpdateTime, file.length()));
            }
        }
        return fileNames;
    }

    private void syncAll() {
        logger.info("flush db begin .. ");
        jedisClusterService.flushAll();

        logger.info("execute sync services begin ..");

        for (SyncService syncService : syncServices) {
            if (syncService.isRunning()) {
                continue;
            }
            syncService.sync();
        }

        logger.info("execute sync services done !!");
    }

    private List<SyncFile> getSyncFiles() {
        ArrayList<SyncFile> syncFiles = new ArrayList<SyncFile>();
        CollectionUtils.addIgnoreNull(syncFiles, loadSyncFile(Constant.SYNC_ROOM_OCCUPANCY_CONFIG));
        CollectionUtils.addIgnoreNull(syncFiles, loadSyncFile(Constant.SYNC_RATE_CACHE_CONFIG));
        CollectionUtils.addIgnoreNull(syncFiles, loadSyncFile(Constant.SYNC_ROOM_STAY_CONFIG));
        return syncFiles;
    }

    private SyncFile loadSyncFile(String variableName) {
        String value = systemVariableRepository.getValue(variableName);
        if (StringUtils.isBlank(value)) {
            value = SyncFile.defaultJson();
            systemVariableRepository.update(variableName, value);
        }
        return SyncFile.fromJson(value);
    }

    public void setSystemVariableRepository(SystemVariableRepository systemVariableRepository) {
        this.systemVariableRepository = systemVariableRepository;
    }

    public void setSyncServices(List<SyncService> syncServices) {
        this.syncServices = syncServices;
    }

    public void setJedisClusterService(JedisClusterService jedisClusterService) {
        this.jedisClusterService = jedisClusterService;
    }

    @Override
    public boolean isRunning() {
        return running.get();
    }
}
